package bigbeard.tools.thread.pools;

import java.util.concurrent.*;

/**
 * @author bigbeard on 2018-09-27
 * 提供创建线程池的工具类
 */
public class ThreadPoolFactory {

    private static final int CORE_POOL_SIZE_10 = 10;
    private static final int MAX_POOL_SIZE_100 = 100;
    private static final int MAX_SINGLE_POOL_SIZE = 1;
    private static final int CORE_SINGLE_POOL_SIZE=1;
    private static final int MAX_QUEUE_SIZE_5000 = 5000;
    private static final int CORE_POOL_SIZE_20 = 20;
    private static final int MAX_POOL_SIZE_2000 = 2000;
    private static final int MAX_QUEUE_SIZE_10000 = 10000;
    private static final long MAX_TIME_KEEP_ALIVE_TIME = 60;

    private static final ThreadPoolManager THREAD_POOL_MANAGER = new ThreadPoolManager();

    /**
     * 创建只有<code>CORE_POOL_SIZE</code>个核心线程
     * 最大<code>MAX_POOL_SIZE</code>个线程
     * 排队为<code>MAX_QUEUE_SIZE_500</code>超出丢弃的线程池
     *
     * @param threadName 线程名称
     * @return 线程池
     */
    public static ExecutorService createNotifyThreadPool(String threadName) {
        return THREAD_POOL_MANAGER.createExecutorService(
                CORE_POOL_SIZE_10, MAX_POOL_SIZE_100,
                new ArrayBlockingQueue<>(MAX_QUEUE_SIZE_10000),
                new ThreadFactoryBuilder().setDaemon(true).setNamePrefix(
                        threadName).build());
    }

    /**
     * 创建只有一个线程的线程池,最大排队数为<code>MAX_QUEUE_SIZE_500</code>
     *
     * @param threadName 线程名称
     * @return 线程池
     */
    public static ExecutorService createSingleThreadPool(String threadName) {
        return THREAD_POOL_MANAGER.createExecutorService(
                CORE_SINGLE_POOL_SIZE, MAX_SINGLE_POOL_SIZE,
                new ArrayBlockingQueue<>(MAX_QUEUE_SIZE_5000),
                new ThreadFactoryBuilder().setDaemon(true).setNamePrefix(
                        threadName).build());
    }

    /**
     * 创建<code>CORE_POOL_SIZE_20</code>个核心线程
     * 最大<code>MAX_POOL_SIZE_100</code>个线程
     * 排队为<code>MAX_QUEUE_SIZE_3000</code>超出丢弃的线程池
     *
     * @param threadName 线程名称
     * @return 线程池
     */
    public static ExecutorService createThreadPool(String threadName) {
        return THREAD_POOL_MANAGER.createExecutorService(
                CORE_POOL_SIZE_20, MAX_POOL_SIZE_2000,
                new ArrayBlockingQueue<>(MAX_QUEUE_SIZE_10000),
                new ThreadFactoryBuilder().setDaemon(true).setNamePrefix(
                        threadName).build());
    }

    /**
     * 创建线程池
     * 排队为<code>MAX_QUEUE_SIZE_3000</code>超出丢弃的线程池
     *
     * @param threadName   线程名称
     * @param corePoolSize 核心线程数
     * @param maxPoolSize  最大线程数
     * @return 线程池
     */
    public static ExecutorService createThreadPool(String threadName, int corePoolSize, int maxPoolSize) {
        return THREAD_POOL_MANAGER.createExecutorService(
                corePoolSize, maxPoolSize,
                new ArrayBlockingQueue<>(MAX_QUEUE_SIZE_10000),
                new ThreadFactoryBuilder().setDaemon(true).setNamePrefix(
                        threadName).build());
    }

    /**
     * 创建线程池,当超出之后系统使用调用线程处理.
     *
     * @param threadName   线程名称
     * @param corePoolSize 核心线程数
     * @param maxPoolSize  最大线程数
     * @param maxQueueSize 最大排队数
     * @return 线程池
     */
    public static ExecutorService createThreadPool(
            String threadName, int corePoolSize, int maxPoolSize, int maxQueueSize) {
        return THREAD_POOL_MANAGER.createExecutorService(
                corePoolSize, maxPoolSize, MAX_TIME_KEEP_ALIVE_TIME,
                new ArrayBlockingQueue<>(maxQueueSize),
                new ThreadFactoryBuilder().setDaemon(true).setNamePrefix(
                        threadName).build(), new ThreadPoolExecutor.CallerRunsPolicy());
    }

    /**
     * 定时执行任务
     *
     * @param corePoolSize  核心线程数量
     * @param task          任务
     * @param interval      间隔时间
     * @param unit          时间单位
     * @param threadFactory 线程构造器
     * @param handle        超过线程最大容量之后的拒绝处理
     * @return 定时构造期
     */
    public static <V> ScheduledExecutorService createSchedule(
            int corePoolSize,
            Callable<V> task,
            int interval,
            TimeUnit unit,
            ThreadFactory threadFactory,
            RejectedExecutionHandler handle) {
        return THREAD_POOL_MANAGER.createSchedule(corePoolSize, task, interval, unit, threadFactory, handle);
    }

    /**
     * 定时执行任务
     *
     * @param threadName 线程名称
     * @param task       任务
     * @param interval   间隔时间
     * @param timeUnit   时间单位
     * @return 定时构造器
     */
    public static <V> ScheduledExecutorService createSchedule(
            String threadName, Callable<V> task, int interval, TimeUnit timeUnit) {
        return createSchedule(CORE_POOL_SIZE_10, task, interval, timeUnit,
                              new ThreadFactoryBuilder().setDaemon(true).setNamePrefix(threadName).build(),
                              new ThreadPoolExecutor.CallerRunsPolicy());
    }


    /**
     * 定时任务
     *
     * @param task     任务
     * @param interval 时间间隔,单位毫秒
     * @param <V>      返回类型
     * @return new ThreadFactoryBuilder().setDaemon(true).setNamePrefix(threadName).build(),
     */
    public static <V> ScheduledExecutorService createSchedule(Callable<V> task, int interval) {
        return createSchedule("Schedule-Thread-%s", task, interval, TimeUnit.MILLISECONDS);
    }

    /**
     * 定时执行任务
     *
     * @param corePoolSize  核心线程数量
     * @param task          任务
     * @param interval      间隔时间
     * @param unit          时间单位
     * @param threadFactory 线程构造器
     * @param handle        超过线程最大容量之后的拒绝处理
     * @return 定时构造期
     */
    public static ScheduledExecutorService createSchedule(
            int corePoolSize,
            Runnable task,
            int interval,
            TimeUnit unit,
            ThreadFactory threadFactory,
            RejectedExecutionHandler handle) {
        return THREAD_POOL_MANAGER.createSchedule(corePoolSize, task, interval, unit, threadFactory, handle);
    }

    /**
     * 定时执行任务
     *
     * @param threadName 线程名称
     * @param task       任务
     * @param interval   间隔时间
     * @param timeUnit   时间单位
     * @return 定时构造器
     */
    public static ScheduledExecutorService createSchedule(
            String threadName, Runnable task, int interval, TimeUnit timeUnit) {
        return createSchedule(CORE_POOL_SIZE_10, task, interval, timeUnit,
                              new ThreadFactoryBuilder().setDaemon(true).setNamePrefix(threadName).build(),
                              new ThreadPoolExecutor.CallerRunsPolicy());
    }


    /**
     * 定时任务
     *
     * @param task     任务
     * @param interval 时间间隔,单位毫秒
     * @return new ThreadFactoryBuilder().setDaemon(true).setNamePrefix(threadName).build(),
     */
    public static ScheduledExecutorService createSchedule(Runnable task, int interval) {
        return createSchedule("Schedule-Thread-%s", task, interval, TimeUnit.MILLISECONDS);
    }
}
